package cn.itcast;

import cn.itcast.pojo.Item;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class RestTest {

    private RestHighLevelClient client = null;
    private Gson gson = new Gson();

    @Before
    public void init() {
        client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9201, "http"),
                        new HttpHost("localhost", 9202, "http"),
                        new HttpHost("localhost", 9203, "http")));

    }

    //新增或修改
    @Test
    public void testDocument() throws IOException {
        //创建item对象并转成json
        Item item = new Item(1L, "小米手机7", "手机", "小米", 3299.00, "http://image.leyou.com/13123.jpg");
        String strJson = gson.toJson(item);
        //创建IndexRequest对象,并连接索引库,和库中的表,以及新增文档的Id
        IndexRequest request = new IndexRequest("item", "docs", item.getId().toString());
        request.source(strJson, XContentType.JSON);
        client.index(request, RequestOptions.DEFAULT);

        //修改 UpdateRequest  不要使用  一直会报错
/*        UpdateRequest request = new UpdateRequest("item","docs","2");
        Item item = new Item(2L,"大米6X手机","手机","小米",1199.0,"http.jpg");
        String jsonStr = gson.toJson(item);
        request.upsert(jsonStr,XContentType.JSON);  //update+insert
        client.update(request,RequestOptions.DEFAULT);*/

    }

    //根据Id查询
    @Test
    public void testDocument1() throws IOException {

        GetRequest request = new GetRequest("item", "docs", "1");
        GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
        String sourceAsString = getResponse.getSourceAsString();
        Item item = gson.fromJson(sourceAsString, Item.class);
        System.out.println(item);

    }

    //删除
    @Test
    public void testDocument2() throws IOException {

        DeleteRequest request = new DeleteRequest("item", "docs", "1");
        client.delete(request, RequestOptions.DEFAULT);

    }

    //批量添加
    @Test
    public void addDocument2() throws IOException {

        List<Item> list = new ArrayList<>();
        list.add(new Item(1L, "小米手机7", "手机", "小米", 3299.00, "http://image.leyou.com/13123.jpg"));
        list.add(new Item(2L, "坚果手机R1", "手机", "锤子", 3699.00, "http://image.leyou.com/13123.jpg"));
        list.add(new Item(3L, "华为META10", "手机", "华为", 4499.00, "http://image.leyou.com/13123.jpg"));
        list.add(new Item(4L, "小米Mix2S", "手机", "小米", 4299.00, "http://image.leyou.com/13123.jpg"));
        list.add(new Item(5L, "荣耀V10", "手机", "华为", 2799.00, "http://image.leyou.com/13123.jpg"));

        BulkRequest bulkRequest = new BulkRequest();
        for (Item item : list) {
            bulkRequest.add(new IndexRequest("item", "docs", item.getId().toString()).source(JSON.toJSONString(item), XContentType.JSON));
        }
        client.bulk(bulkRequest, RequestOptions.DEFAULT);

    }

    //各种条件查询
    @Test
    public void testQuery() throws IOException {
        //参数不可以添加type,构建SearchRequest和SearchSourceBuilder对象
        SearchRequest searchRequest = new SearchRequest("item");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        /*构建查询条件,查询所有
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());*/
      /*构建查询条件,按term查询
        searchSourceBuilder.query(QueryBuilders.termQuery("title","小米"));*/
        //构建查询条件,分词查询
        // searchSourceBuilder.query(QueryBuilders.matchQuery("title","小米手机"));
        //构建查询条件,容错查询
        // searchSourceBuilder.query(QueryBuilders.fuzzyQuery("title","大米").fuzziness(Fuzziness.ONE));
        //构建查询条件,范围查询
        // searchSourceBuilder.query(QueryBuilders.rangeQuery("price").gte(3000).lte(4000));
        //构建查询条件,组合查询
       /* searchSourceBuilder.query(QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("title", "手机"))
                .must(QueryBuilders.rangeQuery("price")
                        .gte(3000).lte(4000)));*/
        //过滤属性查询(要显示的,和不要显示的)
        //searchSourceBuilder.fetchSource(null,"title");
        // searchSourceBuilder.fetchSource(new String[]{"title","category"},null);
        //searchSourceBuilder.query(QueryBuilders.matchAllQuery());

        //查询结果过滤,先按手机条件查询,再按品牌过滤查询
       /* searchSourceBuilder.query(QueryBuilders.termQuery("title","手机"));
        searchSourceBuilder.postFilter(QueryBuilders.termQuery("brand","小米"));*/

        //分页查询
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchSourceBuilder.from(1);
        searchSourceBuilder.size(2);
        //排序
       /* searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchSourceBuilder.sort("id", SortOrder.DESC);  */// 参数1：排序的域名  参数2：顺序
        //开始查询
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits searchHits = searchResponse.getHits();
        long totalHits = searchHits.getTotalHits();
        System.out.println("一共有" + totalHits + "条数据");
        SearchHit[] hits = searchHits.getHits();

        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            Item item = JSON.parseObject(sourceAsString, Item.class);
            System.out.println(item);

        }
    }

    //高亮显示
    @Test
    public void testQuery2() throws IOException {
        //参数不可以添加type,构建SearchRequest和SearchSourceBuilder对象
        SearchRequest searchRequest = new SearchRequest("item");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //构建高亮条件
        searchSourceBuilder.query(QueryBuilders.termQuery("title","小米"));
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font style='color:red'>");
        highlightBuilder.postTags("</font>");
        highlightBuilder.field("title");
        searchSourceBuilder.highlighter(highlightBuilder);

        //开始查询
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits searchHits = searchResponse.getHits();
        long totalHits = searchHits.getTotalHits();
        System.out.println("一共有" + totalHits + "条数据");
        SearchHit[] hits = searchHits.getHits();

        for (SearchHit hit : hits) {
            //获取高亮条件的字段(是一个map类型的)
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            //获取的是一个数组,里面可能有多个样式
            HighlightField highlightField = highlightFields.get("title");
            //获取高亮数组中的高亮字符串
            String title = highlightField.getFragments()[0].string();
            String sourceAsString = hit.getSourceAsString();
            Item item = JSON.parseObject(sourceAsString, Item.class);
            //使用高亮条件的字符串替换原有的字符串
            item.setTitle(title);
            System.out.println(item);

        }
    }

    //聚合查询
    @Test
    public void testQuery3() throws IOException {
        //参数不可以添加type,构建SearchRequest和SearchSourceBuilder对象
        SearchRequest searchRequest = new SearchRequest("item");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //brandAvg名字随便写类似于别名,后面跟字段
        searchSourceBuilder.aggregation(AggregationBuilders.terms("brandAvg").field("brand"));

        //开始查询
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        //参考浏览器中的数据结构,获取聚合
        Aggregations aggregations = searchResponse.getAggregations();
        Terms terms = aggregations.get("brandAvg");
        List<? extends Terms.Bucket> buckets = terms.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            System.out.println(bucket.getKeyAsString()+":"+bucket.getDocCount());
        }
        SearchHits searchHits = searchResponse.getHits();
        long totalHits = searchHits.getTotalHits();
        System.out.println("一共有" + totalHits + "条数据");
        SearchHit[] hits = searchHits.getHits();

        for (SearchHit hit : hits) {

            String sourceAsString = hit.getSourceAsString();
            Item item = JSON.parseObject(sourceAsString, Item.class);
            //使用高亮条件的字符串替换原有的字符串
            System.out.println(item);

        }
    }

    @After
    public void end() throws IOException {
        client.close();
    }
}
